/*
 * @Description: Axios请求拦截方法封装
 * @Author: 0001100986/LiuShuai
 * @Date: 2021-06-22 14:09:49
 * @LastEditTime: 2023-12-27 10:25:54
 * @LastEditors: 0001101008/HuYuxi
 */
import axios from 'axios';
import store from '../store';
import router from '../router';
import { baseUrl } from './config.js';
import { Message } from 'element-ui';
import { httpXhr } from './monitor';
import { loginCSRF } from '@/api/login.js';
import { showScreenLoading, hideScreenLoading } from './loading';

let cancel;
let promiseArr = {};
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

// 重写Message
let messageInstance = null;
const rewriteMessage = (options) => {
  if (messageInstance) {
    messageInstance.close();
  }
  messageInstance = Message(options);
};
['error', 'success', 'info', 'warning'].forEach(type => {
  rewriteMessage[type] = options => {
    if (typeof options === 'string') {
      options = {
        message: options
      };
    }
    options.type = type;
    return rewriteMessage(options);
  };
});

// 请求拦截器
axios.interceptors.request.use(
  config => {
    // 语言种类
    let language = store.state.user.user.language;
    // 全局添加cancelToken
    config.cancelToken = source.token;
    // 发起请求时，取消掉当前正在进行的相同请求
    if (promiseArr[config.url]) {
      promiseArr[config.url](language === 'cn' ? '操作取消' : 'Operation Cancellation');
      promiseArr[config.url] = cancel;
    } else {
      promiseArr[config.url] = cancel;
    }
    // 拼接域名
    config.url = baseUrl + config.url;
    config.headers = {
      'Content-Type': config.contentType ? 'multipart/form-data' : 'application/json;charset=UTF-8',
      'Accept-Language': language === 'cn' ? 'zh-cn' : 'en-us',
      'Loading': config.loading,
      'IsMessage': config.isMessage ? true : false
    };
    if (!config.url.includes('_csrf')) {
      config.headers['X-XSRF-TOKEN'] = sessionStorage.getItem('jwt');
    }
    if (!config.contentType) {
      config.headers.Accept = 'application/json, text/plain, */*';
    }
    if (config.headers.Loading !== false) {
      showScreenLoading(config.headers);
    }
    return config;
  },
  error => {
    hideScreenLoading();
    return Promise.reject(error);
  }
);

// 响应拦截器即异常处理
axios.interceptors.response.use(async (response) => {
  let { status, errorMsg } = response.data;
  let isMessage = response.config.headers.IsMessage;
  // 正常请求报错
  if (status && status !== '0') {
    if (isMessage) {
      // 自定义返回提示信息
      httpXhr('info', response);
    } else {
      httpXhr('info', response);
      rewriteMessage.error(errorMsg);
    }
  }
  // token验证失败，重新登录
  if (response.redirect && response.redirect === '/login.html') {
    router.push('/login');
  }
  if (response) {
    if (response.config.url.includes('_csrf')) {
      let { token } = await loginCSRF();
      sessionStorage.setItem('jwt', token);
    }
    if (status === '0') {
      httpXhr('normal', response);
    }
    setTimeout(() => {
      if (response.config.headers.Loading !== false) {
        hideScreenLoading();
      }
    }, 500);
    return response;
  }
  // eslint-disable-next-line complexity
}, err => {
  let language = store.state.user.user.language;
  if (err && err.response) {
    httpXhr('error', err);
    switch (err.response.status) {
      case 400:
        err.message = language === 'cn' ? '错误请求' : 'Error Request';
        break;
      case 401:
        err.message = typeof err.response.data === 'string' ? err.response.data : language === 'cn' ? '未授权，请重新登录！' : 'Unauthorized, please login again!';
        router.push('/login');
        break;
      case 403:
        err.message = language === 'cn' ? '拒绝访问' : 'Access denied';
        if (err.response.data.error.details.indexOf('Token') > -1 || err.response.data.error.details.indexOf('token') > -1) {
          router.push('/login');
        }
        break;
      case 404:
        err.message = language === 'cn' ? '请求错误,未找到该资源！' : 'The resource was not found!';
        break;
      case 405:
        err.message = language === 'cn' ? '请求方法未允许' : 'Request method not allowed';
        break;
      case 408:
        err.message = language === 'cn' ? '请求超时' : 'Request timeout';
        break;
      case 500:
        if (err.config.responseType === 'blob') {
          const data = err.response.data;
          const reader = new FileReader();
          reader.readAsText(data);
          reader.onload = evt => {
            const msg = JSON.parse(evt.target.result);
            let { status, error } = msg;
            // 文件导出
            if (status === 500) {
              rewriteMessage.error(error.details);
            } else {
              // 验证码获取
              rewriteMessage.error(msg);
            }
          };
        } else {
          if (typeof err.response.data.error.debugMessage === 'string') {
            err.message = err.response.data;
          } else if (typeof err.response.data.error.debugMessage === 'string' || typeof err.response.data.error.details === 'string') {
            err.message = err.response.data.error.debugMessage;
            if (err.response.data.error.details) {
              err.message = err.response.data.error.details;
            }
          } else if (err.response.data.error.message) {
            err.message = err.response.data.error.message;
          } else {
            language === 'cn' ? err.message = '服务器端出错' : err.message = 'Server side error';
          }
        }
        break;
      case 501:
        err.message = language === 'cn' ? '网络未实现' : 'Network not implemented';
        break;
      case 502:
        err.message = language === 'cn' ? '网络错误' : 'Network error';
        break;
      case 503:
        err.message = language === 'cn' ? '服务不可用' : 'Service not available';
        break;
      case 504:
        err.message = language === 'cn' ? '网络超时' : 'Network Timeout';
        break;
      case 505:
        err.message = language === 'cn' ? 'Http版本不支持该请求' : 'Http version does not support this request';
        break;
      default:
        err.message = language === 'cn' ? `连接错误${err.response.status}` : `Connection error ${err.response.status}`;
    }
  } else {
    err.message = language === 'cn' ? '连接到服务器失败' : 'Failed to connect to the server';
  }
  if (err && err.response) {
    rewriteMessage.error(err.message);
  }
  hideScreenLoading();
  return Promise.reject(err);
});

axios.defaults.timeout = 30000;

// get请求方式
function get (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'get',
      params: config.data,
      loading: config.loading === undefined ? false : config.loading,
      isMessage: config.isMessage === undefined ? false : config.isMessage
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

// get请求方式
function getJson (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'get'
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

// get请求方式获取Image
function getImage (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'get',
      params: config.data,
      responseType: 'blob',
      loading: config.loading === undefined ? false : config.loading,
      isMessage: config.isMessage === undefined ? false : config.isMessage
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

// post请求方式
function post (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'post',
      data: config.data,
      loading: config.loading === undefined ? false : config.loading,
      isMessage: config.isMessage === undefined ? false : config.isMessage,
      timeout: config.timeout === undefined ? 30000 : config.timeout
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

function downloadPost (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'post',
      data: config.data,
      responseType: 'blob',
      loading: config.loading === undefined ? false : config.loading
    }).then(res => {
      resolve(res);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

// put请求方式
function put (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'put',
      data: config.data,
      loading: config.loading === undefined ? false : config.loading
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

function uploadPost (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'post',
      contentType: true,
      data: config.data,
      responseType: 'blob',
      loading: config.loading === undefined ? false : config.loading
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

// deleteh请求方式
function deleted (config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,
      method: 'delete',
      data: config.data,
      loading: config.loading === undefined ? false : config.loading
    }).then(res => {
      resolve(res.data);
    }).catch(err => {
      if (err.message === '连接到服务器失败') { rewriteMessage.error('请求超时') }
      if (err.message === 'Failed to connect to the server') { rewriteMessage.error('Request timeout') }
      reject(err);
    });
  });
}

export default {
  get,
  getJson,
  getImage,
  post,
  downloadPost,
  uploadPost,
  put,
  deleted
};
